/*
 *  Copyright (C) 1998-2020 by Northwoods Software Corporation. All Rights Reserved.
 */

import * as go from 'gojs';
import { ReactDiagram } from 'gojs-react';
import * as React from 'react';
import { makeDiagramModal } from './Diagram';
import './Diagram.scss';

interface DiagramProps {
  hotKey: number;
  nodeDataArray: Array<go.ObjectData>;
  linkDataArray: Array<go.ObjectData>;
  modelData: go.ObjectData;
  skipsDiagramUpdate: boolean;
  onDiagramEvent: (e: go.DiagramEvent) => void;
  onModelChange: (e: go.IncrementalData) => void;
}

/**
 * 流程节点调试
 * 示例： AI管理-机器人管理-版本管理-配置话术流程-流程调试
 */
export class DiagramWrapperDebug extends React.Component<DiagramProps, {}> {
  /**
   * Ref to keep a reference to the Diagram component, which provides access to the GoJS diagram via getDiagram().
   */
  private diagramRef: React.RefObject<ReactDiagram>;

  /** @internal */
  constructor(props: DiagramProps) {
    super(props);
    this.diagramRef = React.createRef();
    this.state = {
      myDiagram: null,
    };
  }

  /**
   * Get the diagram reference and add any desired diagram listeners.
   * Typically the same function will be used for each listener, with the function using a switch statement to handle the events.
   * 通常，每个侦听器使用相同的函数，该函数使用switch语句来处理事件
   */
  componentDidMount() {
    console.log('流程调试页面 -> componentDidMount', this.props.nodeDataArray, this.props.hotKey);
    if (!this.diagramRef.current) return;
    const diagram = this.diagramRef.current.getDiagram();
    if (diagram instanceof go.Diagram) {
      diagram.addDiagramListener('ChangedSelection', this.props.onDiagramEvent);
      // mock：为了验证高亮节点功能正常
      // setTimeout(() => {
      //   this.autoHighlight(diagram, 2);
      // }, 1000);
    }
  }

  componentDidUpdate() {
    console.log('流程调试页面 -> componentDidUpdate');
    if (this.props.hotKey) {
      const { hotKey } = this.props;
      const diagram = this.diagramRef.current?.getDiagram();
      if (diagram instanceof go.Diagram) {
        if (hotKey >= 0) {
          this.autoHighlight(diagram, hotKey);
        }
      }
    }
  }

  /**
   * Get the diagram reference and remove listeners that were added during mounting.
   * 获取关系图引用并删除在挂载期间添加的侦听器。
   */
  public componentWillUnmount() {
    if (!this.diagramRef.current) return;
    const diagram = this.diagramRef.current.getDiagram();
    if (diagram instanceof go.Diagram) {
      diagram.removeDiagramListener('ChangedSelection', this.props.onDiagramEvent);
    }
  }

  /**
   * 将某一个节点展示在视线内
   * @param myDiagram
   * @param hotKey
   */
  private srollToNode(myDiagram: go.Diagram, hotKey: number) {
    const node = myDiagram.findNodeForKey(hotKey);
    if (myDiagram && node) {
      myDiagram.commandHandler.scrollToPart(node);
    }
  }

  /**
   * 调试时自动高亮节点功能：滚动至高亮节点
   * @param hotKey
   * @param status
   */
  private autoHighlight(myDiagram: go.Diagram, hotKey: number, status = 1) {
    myDiagram.clearSelection();
    myDiagram.model.nodeDataArray.forEach(item => {
      if (item.key === hotKey) {
        item.status = status; // nodeStatusConverter
      } else {
        item.status = 0;
      }
      myDiagram.model.updateTargetBindings(item);
    });
    // this.highlightLink(myDiagram, hotKey, status);

    this.srollToNode(myDiagram, hotKey);
  }

  /**连线高亮显示
   * @param myDiagram 视图
   * @param hotKey 高亮节点
   * @status 节点状态
   */
  private highlightLink(myDiagram: go.Diagram, hotKey: number, status = 1) {
    // @ts-ignore：忽略检测, 应该是GoJS没有进行TS声明
    myDiagram.model.linkDataArray.forEach(item => {
      if (item.to === hotKey) {
        item.status = status; // linkStatusConverter
      } else {
        item.status = 0;
      }
      myDiagram.model.updateTargetBindings(item);
    });
  }

  // 初始化图表
  private initDiagramModel = () => makeDiagramModal({ isDebug: true });

  public render() {
    return (
      <div className="diagram_container">
        <ReactDiagram
          ref={this.diagramRef}
          divClassName="diagram-component"
          initDiagram={this.initDiagramModel}
          nodeDataArray={this.props.nodeDataArray}
          linkDataArray={this.props.linkDataArray}
          modelData={this.props.modelData}
          onModelChange={this.props.onModelChange}
          skipsDiagramUpdate={this.props.skipsDiagramUpdate}
        />
      </div>
    );
  }
}
